Tired of waiting around for anonymous closures to arrive in C++0x (or at least in GCC)? Boost.Lambda and other hacks leaving you pining for something with free variable capture? Get them today with the amazing C++ Lambda Preprocessor (“clamp”)!
Here’s a little demo illustrating the use of lambdas with threads—something which may be more interesting to systems programmers than the simple accumulator examples on the clamp homepage.
#include <boost/thread.hpp>
#include <iostream>
using namespace boost;
using namespace std;
#include "lambda_impl.clamp_h"
enum { n = 3 };
int main() {
const string msgs[n] = {"first", "second", "third"};
mutex m;
for (int i = 0; i < n; ++i) {
boost::thread(lambda() {
mutex::scoped_lock l(__ref(m));
cout << "message from thread " << __ctx(i)
<< ": " << __ref(msgs[i]) << endl;
});
}
return 0;
}
// clamp < clamp2.cc.clamp | sed '1d' > clamp2.cc
// g++ clamp2.cc -lboost_thread-gcc43-mt -o clamp2
// ./clamp2
There are a few annoyances with clamp:
- All free variables must be explicitly captured with
__ref()or__ctx(). This is because clamp doesn’t try to actually parse your C++ (understandably). (Not parsing the C++ also makes it more flexible, accommodating various language extensions.) Contrast this with C++0x, where you can use short-hand notations like[&], which captures all free variables by reference (perhaps the most common case). - You will most likely need to muck with the output. clamp generates a number of header files that form the first
#includein your source file. However, if you ever refer to global types/variables/functions, you will need to reorder things, add forward declarations, separate the generated header contents into declarations and definitions, etc. This is made nearly trivial, however, if you also use Lazy C++, which I’ll cover next time.
Despite these minor quibbles, clamp is simple and effective. The generated code is straightforward—pretty much exactly what you would expect to write yourself by hand.